package com.ruyuan.seckilling.activity.schedule;

import com.google.common.collect.ImmutableMap;
import com.ruyuan.seckilling.activity.constant.ActivityStatusVal;
import com.ruyuan.seckilling.activity.entity.Activity;
import com.ruyuan.seckilling.activity.entity.ActivitySkuRef;
import com.ruyuan.seckilling.activity.service.ActivityService;
import com.ruyuan.seckilling.activity.service.ActivitySkuRefService;
import com.ruyuan.seckilling.common.CacheKey;
import com.ruyuan.seckilling.common.FileNameUtils;
import com.ruyuan.seckilling.common.QueueKey;
import com.ruyuan.seckilling.common.message.PageRenderMessage;
import com.ruyuan.starter.jedis.LockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author zhonghuashishan
 */
@Slf4j
@Component
public class TriggerPageTask {

    @Autowired
    private ActivityService activityService;

    @Autowired
    private ActivitySkuRefService activitySkuRefService;

    @Autowired
    private LockService lockService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Scheduled(fixedDelay = 10_000)
    public void run() {
        String lockToken = lockService.tryLock(CacheKey.TRIGGER_PAGE_LOCK, 1, TimeUnit.SECONDS);
        if (lockToken == null) {
            return;
        }
        log.info("触发渲染页面，获取分布式锁成功, lockToken={}", lockToken);
        try {
            // 在秒杀活动展示之前1小时开始渲染页面
            List<Activity> activities = activityService.queryListForTriggerPageTask();
            if (CollectionUtils.isEmpty(activities)) {
                return;
            }

            for (Activity activity : activities) {
                Long id = activity.getId();
                List<ActivitySkuRef> activitySkuRefs = activitySkuRefService.queryByActivityId(id);
                if (CollectionUtils.isEmpty(activitySkuRefs)) {
                    continue;
                }

                // 发送渲染秒杀活动商品列表页面的消息
                List<Long> skuIds = activitySkuRefs.stream().map(ActivitySkuRef::getSkuId).collect(Collectors.toList());
                String renderActivityPageMessage = PageRenderMessage.builder()
                        .pageCode("seckilling_activity")
                        .bizData(ImmutableMap.of("type", "activity", "activityId", id))
                        .params(ImmutableMap.of("activityId", id,
                                "activityName", activity.getActivityName(),
                                "startTime", activity.getStartTime(),
                                "endTime", activity.getEndTime(),
                                "skuIds", skuIds))
                        .fileName(FileNameUtils.generateSeckillingActivityFilename(id))
                        .build().toJsonString();
                rocketMQTemplate.syncSend(QueueKey.QUEUE_RENDER_PAGE, renderActivityPageMessage);
                log.info("触发渲染页面，发送渲染商品列表页面的消息, message={}", renderActivityPageMessage);

                for (ActivitySkuRef activitySkuRef : activitySkuRefs) {
                    // 发送渲染秒杀商品详情页面的消息
                    Long skuId = activitySkuRef.getSkuId();
                    String renderProductPageMessage = PageRenderMessage.builder()
                            .pageCode("seckilling_product")
                            .bizData(ImmutableMap.of("type", "product", "activityId", id, "skuId", skuId))
                            .params(ImmutableMap.of("skuId", skuId))
                            .fileName(FileNameUtils.generateSeckillingProductFilename(skuId))
                            .build().toJsonString();
                    rocketMQTemplate.syncSend(QueueKey.QUEUE_RENDER_PAGE, renderProductPageMessage);
                    log.info("触发渲染页面，发送渲染商品详情页面的消息, message={}", renderProductPageMessage);
                }

                // 把活动的状态修改为页面渲染中
                activityService.updataStatus(id, ActivityStatusVal.AUDIT_PASS.getCode(),
                        ActivityStatusVal.PAGE_RENDERING.getCode());
                log.info("触发渲染页面，把活动状态改成页面渲染中");
            }
        } finally {
            lockService.release(CacheKey.TRIGGER_PAGE_LOCK, lockToken);
            log.info("触发渲染页面，释放分布式锁");
        }
    }
}
